/**
 * @author Greg Feigenson
 * @version RC1
 * @date 05/10/2004
 *
 * The actual conf parser. This is a singleton because
 *  it deals with IO on a file
 * and it's simpler than writing locks or a monitoring system for the file.
 * You should only be using this either for the conf program, or the main
 * of the HOG system. Technically, this is so general that you can use it
 * on another project should you please (as long as you adhere to licensing)
 *
 * This code comes from IRCD Phoenix (http://ircd-phoenix.sourceforge.net)
 * which is released under the BSD license.
 *
 * Please refer to BSD.LICENSE found in this directory
 */

package conf;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

public final class ConfParser {
    /* Constructor is a Singleton */
    private ConfParser() {

    }

    /* Public Methods */
    public static ConfParser getParser() {
        if (instance == null) {
            instance = new ConfParser();
        }
        return instance;
    }

    public void setFile(final String filename) {
        file = new File(filename);
        if (file.exists()) {
            return;
        } else {
            file = null;
            System.out
                    .println("Error: ConfParser.setFile called on non-existent file");
        }
    }

    public Hashtable parse() {
        if (file == null) {
            System.out
                    .println("Error: ConfParser.parse(): Please call setFile() first");
            return null;
        }

        openFile(file);
        Hashtable hash = readFile();

        return hash;
    }

    public Iterator<?> iterator() {
        if (hash == null || hash.isEmpty()) {
            System.out
                    .println("ConfParser.iterator(): Cannot iterate a null/empty hashmap");
            return null;
        }

        Iterator<?> collection = hash.values().iterator();

        return collection;
    }

    public void writeConf(final Vector<Object> conf) {
        Iterator<Object> iterator = conf.iterator();
        String line;
        openFile(file);
        try {
            PrintWriter out = new PrintWriter(new FileWriter(file), true); // set
                                                                           // autoflush
            while (iterator.hasNext()) {
                line = (String) iterator.next();
                if (!line.equals("") && line != null) {
                    out.println(line);
                }
            }
        } catch (IOException IOE) {
            IOE.printStackTrace();
        }
    }

    /* Private Methods - Mostly FileIO */
    private void openFile(final File theFile) {
        try {
            reader = new BufferedReader(new FileReader(theFile));
        } catch (FileNotFoundException FNFE) {
            FNFE.printStackTrace();
        }
    }

    private void shutdown() {
        try {
            reader.close();
        } catch (IOException IOE) {
            IOE.printStackTrace();
        }
    }

    /*
     * Hash table is constructed to look like this: (assuming input of
     * test:string:1:2:3)
     * 
     * Index | Value ================================ test | string:1:2:3
     */

    private Hashtable readFile() {
        hash.clear(); // flush hash
        String line = new String();
        String[] temp;
        try {
            // FIXME:chokes on empty conf
            while ((line = reader.readLine()) != null) {
                temp = hashIndex(line);
                if (temp != null) {
                    hash.put(temp[0], temp[1]);
                }
            }
        } catch (IOException IOE) {
            IOE.printStackTrace();
        }

        return hash;
    }

    /* Split a string into a hashtable index and a value */
    private String[] hashIndex(final String input) {
        if (input == null) {
            return null;
        }
        String[] result = new String[2]; // result[0] is key, result[1] is value
        int index = input.indexOf(":");
        result[0] = input.substring(0, index);
        result[1] = input.substring(index + 1);

        return result;
    }

    private static BufferedReader reader;
    private static File file;
    private static ConfParser instance;
    private static final Hashtable hash = new Hashtable();
}
